A buffer is an area of storage that temporarily holds data between the time it is generated by an input device and the time that it is actually used by some other component such as a computer or a computer process. One purpose of a buffer is to accommodate the different rates at which data is produced and consumed.
Printing from a computer-based word processing application illustrates the need for buffering. Typically, the word processing application is capable of producing print data several orders of magnitude faster than a printer can accept it. Rather than making the word processor wait for the printer, a computer operating system accepts the data from the word processor and stores it in a buffer. The operating system then feeds the data to the printer from the buffer at an appropriate rate, while the word processor continues with other work.
Keyboard input is another common task for which buffering is used. At any particular moment, an application program or other client for which a keystroke is destined may or may not be ready to receive keystroke data. Accordingly, an operating system stores keystroke data in a buffer, and then provides it to application programs when they specifically request it.
FIG. 1 illustrates a ring buffer 8 such as commonly used to buffer input data from computer input peripherals such as keyboards. A ring buffer, also referred to as a circular buffer, has a plurality of storage registers 9 that are typically located in a contiguous portion of addressable computer memory, extending from a start register having a start address to an end register having an end address. The registers are maintained so that they appear to "wrap around" in a circle, so that the last register is adjacent the first.
The appearance of circular organization is accomplished by using two pointers: a write pointer and a read pointer. Each pointer references a particular location or register in the buffer. The write buffer indicates the next register to which input data should be written. The read buffer indicates the next location for reading from the buffer.
Initially, when the buffer is empty, both the write pointer and the read pointer reference the same register. When a data element is received from a producer such as a keyboard, the data is written to the location referenced by the write pointer, and the write pointer is advanced so that it references the next register in the buffer. Data received from the producer thus begins to fill the buffer, starting from the start register. To consume data, an element is taken from the register referenced by the read pointer. The read pointer advances after each read, so that it always references the next location from which data should be read. After either pointer reaches the point where it references the end register, the next advance moves or changes the pointer so that it references the address of the start register rather than the next numerical address.
If the data consumer is slow, it is possible for the buffer to fill completely. The buffer is full when the write pointer references the register that immediately precedes the register referenced by the read pointer. As a result of this convention, the capacity of a ring buffer is actually one less than the number of registers that form the ring buffer. The unoccupied register referenced by the write pointer is referred to as a "sentinel" register.
If additional data is received when the buffer is full, there are two possible responses. One response is to simply discard any new input data, without writing it to the buffer. Another response is write the new data after arbitrarily advancing the read pointer. This latter option has the effect of discarding the oldest data, while preserving the most recently entered data.
As more and more input peripheral devices are created for use with home computers, there is an increasing need for concurrent transparent access to such devices from multiple application programs. A VCR-type remote control device is an example of an input device whose input might be needed by multiple application programs or processes within a computer. Certain buttons, such as media transport controls, might produce data that is needed by one application program, while other buttons, such as menu control buttons, might produce data needed by another application program.
In the popular Windows.RTM. operating system, an application program receives buffered data input from peripherals by "opening" the peripherals using system API (application programming interface) calls. It would be desirable for different application programs to be able to open the same input device, and to read data from the device without affecting the sequence of data elements provided to other devices from the input device. It would be desirable to accomplish this without requiring the operating system to use multiple ring buffers.